package matchs

import (
	"context"
	"encoding/json"
	"errors"
	"time"

	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/matchs"
	"github.com/flipped-aurora/gin-vue-admin/server/model/matchs/response"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

type SearchService struct{}

var SearchServiceApp = new(SearchService)

// CreateSearchTask 创建寻访任务
func (s *SearchService) CreateSearchTask(ctx context.Context, userId uint64, targetProfessionalIDs []uint, filterCity string, filterGrade string, sortStrategy int8) (uint64, error) {
	// 参数验证
	if userId == 0 {
		return 0, errors.New("用户ID不能为空")
	}
	if len(targetProfessionalIDs) == 0 {
		return 0, errors.New("目标专业ID不能为空")
	}

	// 序列化目标专业ID
	professionalIDsJSON, err := json.Marshal(targetProfessionalIDs)
	if err != nil {
		return 0, errors.New("序列化目标专业ID失败")
	}

	// 设置默认排序策略
	if sortStrategy == 0 {
		sortStrategy = matchs.MatchFindSortRecentLogin
	}

	var taskId uint64
	// 使用事务创建任务
	err = global.GVA_DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 创建寻访任务
		expireAt := time.Now().AddDate(0, 0, 15) // 默认15天过期
		task := matchs.MatchSearchTask{
			UserID:                userId,
			TargetProfessionalIDs: string(professionalIDsJSON),
			FilterCity:            filterCity,
			FilterGrade:           filterGrade,
			SortStrategy:          sortStrategy,
			Status:                matchs.MatchFindStatusPending,
			ExpireAt:              expireAt,
		}

		if err := tx.Create(&task).Error; err != nil {
			return errors.New("创建寻访任务失败")
		}

		taskId = uint64(task.ID)

		// 创建MatchLog记录
		logPayload := map[string]interface{}{
			"targetProfessionalIds": targetProfessionalIDs,
			"filterCity":            filterCity,
			"filterGrade":           filterGrade,
			"sortStrategy":          sortStrategy,
			"expireAt":              expireAt,
		}
		payloadJSON, _ := json.Marshal(logPayload)

		matchLog := matchs.MatchLog{
			TaskType: matchs.MatchRelationTaskTypeFind, // 找人任务类型
			TaskID:   taskId,
			UserID:   userId,
			Action:   matchs.MatchLogActionTaskCreated,
			Payload:  string(payloadJSON),
		}

		if err := tx.Create(&matchLog).Error; err != nil {
			global.GVA_LOG.Error("创建匹配日志失败", zap.Error(err))
		}

		// 异步生成推荐列表
		go s.generateRecommendList(ctx, taskId, targetProfessionalIDs, filterCity, filterGrade, sortStrategy)

		return nil
	})

	return taskId, err
}

// generateRecommendList 生成推荐列表（异步执行）
func (s *SearchService) generateRecommendList(ctx context.Context, taskId uint64, targetProfessionalIDs []uint, filterCity string, filterGrade string, sortStrategy int8) {
	// 构建查询条件
	query := global.GVA_DB.Model(&system.SysUser{}).Where("major IN ? AND id != ? AND auth_status > 0", targetProfessionalIDs, global.GVA_DB.Raw("SELECT user_id FROM match_find_task WHERE id = ?", taskId))

	// 添加城市筛选
	if filterCity != "" {
		query = query.Where("origin_setting ->> '$.city' = ?", filterCity)
	}

	// 添加年级/职级筛选
	if filterGrade != "" {
		query = query.Where("grade = ?", filterGrade)
	}

	// 根据排序策略进行排序
	switch sortStrategy {
	case matchs.MatchFindSortRecentLogin:
		query = query.Order("active_time DESC")
	case matchs.MatchFindSortCommunityLevel:
		// 假设有一个社区等级字段，如果没有可以根据其他指标计算
		query = query.Order("article_count DESC, follower_count DESC")
	case matchs.MatchFindSortInteraction:
		// 假设有互动率字段，如果没有可以根据其他指标计算
		query = query.Order("follower_count DESC")
	}

	// 限制推荐数量
	var recommendedUsers []system.SysUser
	if err := query.Limit(50).Find(&recommendedUsers).Error; err != nil {
		global.GVA_LOG.Error("生成推荐列表失败", zap.Error(err))
		// 更新任务状态为推荐失败
		global.GVA_DB.Model(&matchs.MatchSearchTask{}).Where("id = ?", taskId).Updates(map[string]interface{}{
			"status":      matchs.MatchFindStatusRecommendFailed,
			"fail_reason": "查询推荐用户失败",
		})
		return
	}

	// 如果没有找到推荐用户
	if len(recommendedUsers) == 0 {
		global.GVA_DB.Model(&matchs.MatchSearchTask{}).Where("id = ?", taskId).Updates(map[string]interface{}{
			"status":      matchs.MatchFindStatusRecommendFailed,
			"fail_reason": "未找到符合条件的用户",
		})
		return
	}

	// 批量插入推荐记录
	var recommends []matchs.MatchSearchRecommend
	for i, user := range recommendedUsers {
		recommends = append(recommends, matchs.MatchSearchRecommend{
			TaskID:       taskId,
			TargetUserID: uint64(user.ID),
			Rank:         i + 1,
			Status:       matchs.MatchRecommendStatusPending,
		})
	}

	if err := global.GVA_DB.Create(&recommends).Error; err != nil {
		global.GVA_LOG.Error("插入推荐记录失败", zap.Error(err))
		return
	}

	// 添加MatchLog记录 - 记录推荐用户事件
	var task matchs.MatchSearchTask
	if err := global.GVA_DB.First(&task, taskId).Error; err == nil {
		// 提取推荐用户ID列表用于日志
		var recommendedUserIds []uint64
		for _, user := range recommendedUsers {
			recommendedUserIds = append(recommendedUserIds, uint64(user.ID))
		}

		logPayload := map[string]interface{}{
			"recommendedUserIds": recommendedUserIds,
			"totalCount":         len(recommendedUserIds),
			"filterCity":         filterCity,
			"filterGrade":        filterGrade,
			"sortStrategy":       sortStrategy,
		}
		payloadJSON, _ := json.Marshal(logPayload)

		matchLog := matchs.MatchLog{
			TaskType: matchs.MatchRelationTaskTypeFind,
			TaskID:   taskId,
			UserID:   task.UserID,
			Action:   matchs.MatchLogActionCandidateRecommended,
			Payload:  string(payloadJSON),
		}

		if err := global.GVA_DB.Create(&matchLog).Error; err != nil {
			global.GVA_LOG.Error("创建推荐日志失败", zap.Error(err))
		}
	}

	// 更新任务状态为已推荐
	global.GVA_DB.Model(&matchs.MatchSearchTask{}).Where("id = ?", taskId).Update("status", matchs.MatchFindStatusRecommended)
}

// GetUserSearchTaskList 获取用户发起的寻访任务列表
func (s *SearchService) GetUserSearchTaskList(ctx context.Context, userId uint64, status int8, page, pageSize int) ([]response.SearchTaskVO, int64, error) {
	var tasks []matchs.MatchSearchTask
	var total int64

	offset := (page - 1) * pageSize
	db := global.GVA_DB.Model(&matchs.MatchSearchTask{}).Where("user_id = ?", userId)

	// 状态筛选
	if status >= 0 {
		db = db.Where("status = ?", status)
	}

	// 统计总数
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, errors.New("统计任务总数失败")
	}

	// 分页查询
	if err := db.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&tasks).Error; err != nil {
		return nil, 0, errors.New("查询任务列表失败")
	}

	// 转换为VO
	var taskVOs []response.SearchTaskVO
	for _, task := range tasks {
		taskVOs = append(taskVOs, s.convertToSearchTaskVO(&task))
	}

	return taskVOs, total, nil
}

// GetSearchTaskRecommendList 获取寻访任务推荐的用户列表
func (s *SearchService) GetSearchTaskRecommendList(ctx context.Context, userId, taskId uint64, page, pageSize int) ([]response.RecommendUserVO, int64, error) {
	// 验证任务是否属于该用户
	var task matchs.MatchSearchTask
	if err := global.GVA_DB.Where("id = ? AND user_id = ?", taskId, userId).First(&task).Error; err != nil {
		return nil, 0, errors.New("任务不存在或无权访问")
	}

	var recommends []matchs.MatchSearchRecommend
	var total int64
	offset := (page - 1) * pageSize

	// 统计总数
	db := global.GVA_DB.Model(&matchs.MatchSearchRecommend{}).Where("task_id = ?", taskId)
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, errors.New("统计推荐用户总数失败")
	}

	// 分页查询
	if err := db.Order("rank ASC").Offset(offset).Limit(pageSize).Find(&recommends).Error; err != nil {
		return nil, 0, errors.New("查询推荐用户列表失败")
	}

	// 获取用户信息
	var userIds []uint64
	for _, recommend := range recommends {
		userIds = append(userIds, recommend.TargetUserID)
	}

	var users []system.SysUser
	if err := global.GVA_DB.Where("id IN ?", userIds).Find(&users).Error; err != nil {
		return nil, 0, errors.New("查询用户信息失败")
	}

	// 构建用户信息映射
	userMap := make(map[uint64]system.SysUser)
	for _, user := range users {
		userMap[uint64(user.ID)] = user
	}

	// 转换为VO
	var recommendVOs []response.RecommendUserVO
	for _, recommend := range recommends {
		user, exists := userMap[recommend.TargetUserID]
		if exists {
			recommendVOs = append(recommendVOs, s.convertToRecommendUserVO(&recommend, &user))
		}
	}

	return recommendVOs, total, nil
}

// SkipRecommendUser 跳过推荐用户
func (s *SearchService) SkipRecommendUser(ctx context.Context, userId, taskId, recommendId uint64) error {
	// 验证任务是否属于该用户
	var task matchs.MatchSearchTask
	if err := global.GVA_DB.Where("id = ? AND user_id = ?", taskId, userId).First(&task).Error; err != nil {
		return errors.New("任务不存在或无权访问")
	}

	// 获取推荐用户信息用于日志记录
	var recommend matchs.MatchSearchRecommend
	if err := global.GVA_DB.Where("id = ? AND task_id = ?", recommendId, taskId).First(&recommend).Error; err != nil {
		return errors.New("推荐记录不存在")
	}

	// 更新推荐状态为已跳过
	result := global.GVA_DB.Model(&matchs.MatchSearchRecommend{}).Where("id = ? AND task_id = ?", recommendId, taskId).Update("status", matchs.MatchRecommendStatusSkipped)
	if result.Error != nil {
		return errors.New("跳过推荐用户失败")
	}
	if result.RowsAffected == 0 {
		return errors.New("推荐记录不存在或无权操作")
	}

	// 添加MatchLog记录 - 记录跳过推荐用户事件
	logPayload := map[string]interface{}{
		"recommendId":  recommendId,
		"targetUserId": recommend.TargetUserID,
	}
	payloadJSON, _ := json.Marshal(logPayload)

	matchLog := matchs.MatchLog{
		TaskType: matchs.MatchRelationTaskTypeFind,
		TaskID:   taskId,
		UserID:   userId,
		Action:   matchs.MatchLogActionCandidateSkipped,
		Payload:  string(payloadJSON),
	}

	if err := global.GVA_DB.Create(&matchLog).Error; err != nil {
		global.GVA_LOG.Error("创建跳过推荐日志失败", zap.Error(err))
	}

	return nil
}

// CommunicateWithRecommendUser 沟通推荐用户
func (s *SearchService) CommunicateWithRecommendUser(ctx context.Context, userId, taskId, recommendId uint64, firstMessage string) (string, error) {
	// 验证任务是否属于该用户
	var task matchs.MatchSearchTask
	if err := global.GVA_DB.Where("id = ? AND user_id = ?", taskId, userId).First(&task).Error; err != nil {
		return "", errors.New("任务不存在或无权访问")
	}

	// 获取推荐用户信息
	var recommend matchs.MatchSearchRecommend
	if err := global.GVA_DB.Where("id = ? AND task_id = ?", recommendId, taskId).First(&recommend).Error; err != nil {
		return "", errors.New("推荐记录不存在")
	}

	// 检查推荐状态
	if recommend.Status != matchs.MatchRecommendStatusPending {
		return "", errors.New("该推荐用户已被处理过")
	}

	// 使用事务更新状态并创建聊天记录
	var chatId string
	err := global.GVA_DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 生成聊天ID（实际应该调用IM服务）
		chatId = "chat_" + time.Now().Format("20060102150405") + "_" + string(rune(userId)) + "_" + string(rune(recommend.TargetUserID))

		// 更新推荐状态
		if err := tx.Model(&recommend).Update("status", matchs.MatchRecommendStatusInitiated).Error; err != nil {
			return errors.New("更新推荐状态失败")
		}

		// 更新任务状态为已沟通
		if err := tx.Model(&task).Update("status", matchs.MatchFindStatusCommunicating).Error; err != nil {
			return errors.New("更新任务状态失败")
		}

		// 创建匹配关系记录
		matchRelation := matchs.MatchRelation{
			InitiatorID: userId,
			TargetID:    recommend.TargetUserID,
			TaskType:    matchs.MatchRelationTaskTypeFind,
			TaskID:      taskId,
			Status:      matchs.MatchRelationStatusCommunicating,
		}

		if err := tx.Create(&matchRelation).Error; err != nil {
			return errors.New("创建匹配关系失败")
		}

		// 添加MatchLog记录 - 记录发起沟通事件
		logPayload := map[string]interface{}{
			"recommendId":  recommendId,
			"targetUserId": recommend.TargetUserID,
			"chatId":       chatId,
			"firstMessage": firstMessage,
		}
		payloadJSON, _ := json.Marshal(logPayload)

		matchLog := matchs.MatchLog{
			TaskType: matchs.MatchRelationTaskTypeFind,
			TaskID:   taskId,
			UserID:   userId,
			Action:   matchs.MatchLogActionCommunicationInitiated,
			Payload:  string(payloadJSON),
		}

		if err := tx.Create(&matchLog).Error; err != nil {
			global.GVA_LOG.Error("创建沟通日志失败", zap.Error(err))
			// 日志记录失败不影响主流程
		}

		return nil
	})

	return chatId, err
}

// CompleteSearchTask 完成寻访任务并评分
func (s *SearchService) CompleteSearchTask(ctx context.Context, userId, taskId, recommendId uint64, score int, comment string) error {
	// 验证任务是否属于该用户
	var task matchs.MatchSearchTask
	if err := global.GVA_DB.Where("id = ? AND user_id = ?", taskId, userId).First(&task).Error; err != nil {
		return errors.New("任务不存在或无权访问")
	}

	// 验证评分范围
	if score < 1 || score > 5 {
		return errors.New("评分必须在1-5之间")
	}

	// 验证推荐记录
	var recommend matchs.MatchSearchRecommend
	if err := global.GVA_DB.Where("id = ? AND task_id = ? AND status = ?", recommendId, taskId, matchs.MatchRecommendStatusInitiated).First(&recommend).Error; err != nil {
		return errors.New("推荐记录不存在或未发起沟通")
	}

	// 使用事务更新状态并记录评分
	return global.GVA_DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 更新推荐状态为已完成
		if err := tx.Model(&recommend).Update("status", matchs.MatchRecommendStatusCompleted).Error; err != nil {
			return errors.New("更新推荐状态失败")
		}

		// 更新任务状态为已完成
		if err := tx.Model(&task).Update("status", matchs.MatchFindStatusCompleted).Error; err != nil {
			return errors.New("更新任务状态失败")
		}

		// 创建评分记录
		// 这里假设有一个评分表，如果没有可以创建或者记录在其他表中
		ratingPayload := map[string]interface{}{
			"score":   score,
			"comment": comment,
		}
		ratingJSON, _ := json.Marshal(ratingPayload)

		// 创建日志记录
		matchLog := matchs.MatchLog{
			TaskType: matchs.MatchRelationTaskTypeFind,
			TaskID:   taskId,
			UserID:   userId,
			Action:   matchs.MatchLogActionRated,
			Payload:  string(ratingJSON),
		}

		if err := tx.Create(&matchLog).Error; err != nil {
			global.GVA_LOG.Error("创建评分日志失败", zap.Error(err))
		}

		return nil
	})
}

// convertToSearchTaskVO 转换为任务VO
func (s *SearchService) convertToSearchTaskVO(task *matchs.MatchSearchTask) response.SearchTaskVO {
	// 状态映射字典
	statusMap := map[int8]string{
		matchs.MatchFindStatusPending:         "待处理",
		matchs.MatchFindStatusRecommended:     "已推荐",
		matchs.MatchFindStatusCommunicating:   "已沟通",
		matchs.MatchFindStatusCompleted:       "已结束",
		matchs.MatchFindStatusCancelled:       "已取消",
		matchs.MatchFindStatusRecommendFailed: "推荐失败",
	}

	// 反序列化TargetProfessionalIDs
	var professionalIDs []uint
	if err := json.Unmarshal([]byte(task.TargetProfessionalIDs), &professionalIDs); err != nil {
		professionalIDs = []uint{}
	}

	return response.SearchTaskVO{
		Id:                    task.ID,
		TargetProfessionalIDs: professionalIDs,
		FilterCity:            task.FilterCity,
		FilterGrade:           task.FilterGrade,
		SortStrategy:          task.SortStrategy,
		Status:                task.Status,
		StatusDesc:            statusMap[task.Status],
		FailReason:            task.FailReason,
		ExpireAt:              task.ExpireAt,
		CreatedAt:             task.CreatedAt,
	}
}

// convertToRecommendUserVO 转换为推荐用户VO
func (s *SearchService) convertToRecommendUserVO(recommend *matchs.MatchSearchRecommend, user *system.SysUser) response.RecommendUserVO {
	// 状态映射字典
	statusMap := map[int8]string{
		matchs.MatchRecommendStatusPending:   "待展示",
		matchs.MatchRecommendStatusSkipped:   "已跳过",
		matchs.MatchRecommendStatusInitiated: "已发起沟通",
		matchs.MatchRecommendStatusCompleted: "已完成",
		matchs.MatchRecommendStatusRejected:  "已拒绝",
	}

	return response.RecommendUserVO{
		Id:           uint64(recommend.ID),
		TargetUserId: recommend.TargetUserID,
		UserName:     user.NickName,
		HeaderImg:    user.HeaderImg,
		Major:        user.Major,
		Grade:        user.Grade,
		Rank:         recommend.Rank,
		Status:       recommend.Status,
		StatusDesc:   statusMap[recommend.Status],
		ChatId:       recommend.ChatID,
	}
}
